home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / utils / stlogin4.lzh / GETTY.C < prev    next >
C/C++ Source or Header  |  1993-10-10  |  11KB  |  385 lines

  1. /* UNIX like GETTY program. Kees Lemmens; Aug '92
  2.  
  3.    This program provides a way to start a shell on a remote line
  4.    such as a modem.
  5.    It can be run on an ATARI without MINT multitasking kernel, but
  6.    only with MINT you'll be able to run on the background !
  7.    If you're not using MINT you also have to recompile with new pathnames
  8.    for "wtmp", "passwd", other signal handling (predefined in this source)
  9.    and with an empty "devpath" .
  10.    
  11. Features:
  12.  
  13. -  Can handle (Hayes) modem lines as well as hardwired terminals.
  14. -  Redirects in and output to any line (or pipe) specified in <tty>.
  15. -  Searches the username in the passwordfile and determines from
  16.    there the SHELL and the (encrypted) PWD.
  17. -  Suppresses echo while entering the password.
  18. -  If the user is found and the password is alright it starts the program
  19.    defined in SHELL. It restores the login prompt after the shell has
  20.    finished on a direct line, a modemline receives a hangup.
  21. -  Writes a log entry in (UNIX-like) UTMP and WTMP files to see who logged
  22.    in where and when. WTMP logging is only used if there's is already an
  23.    existing (empty ?) WTMP file. 
  24.    The same applies for a BTMP file, where bad logins will be logged.
  25.    UTMP will be created if it does not exist.
  26. -  Puts the username and home directory in the environment as variables
  27.    LOGNAME and HOME. Also TTYNAME and an initial PATH variable is set.
  28. -  The getty program aborts when a modemline does not respond with "OK"
  29.    when the program sends an initial reset to the modem (ATZ).
  30. -  Can also be run in background mode with the -d option (only MINT !)
  31. -  Number of rings before answering the modemline can be adjusted by
  32.    the -r option. (default after 1 ring)
  33.  
  34. Known Bugs:
  35.  
  36. -  The baudrate can only be set for the current serial line, i.e. the
  37.    AUX: line. This implies that you have to set the RS232 parameters
  38.    manually for other getty lines. This is because the ATARI Rsconf()
  39.    routine only works for the current line.
  40.    It seems however that this is improved since MINT version 1.08.
  41. -  The UTMP and WTMP entries are only partly filled in.
  42.    Take care: WTMP and BTMP are never truncated, so they grow without bounds.
  43. -  The program checks for the presence of MINT. It can also run under
  44.    normal TOS, but it can only do the most basical things then !
  45.    In this case it can only work with the AUX: line; shells and the
  46.    passwd file must be on drive c: (passwd in /etc)
  47.  
  48. In your own password file it is important to have passwords with the
  49. right encryption in your entries, or else you won't be able to login !
  50. Here I used a (simple) algorithm like EOR with 19+positionnr. , but
  51. you're free of course to choose your own !
  52.  
  53. Version 1.1 : Stderr redirection fixed
  54. (Oct 92)      Pid logged in wtmp
  55.               Shell now forks in stead of running as subprocess
  56.               Can also run in background mode without using bg.ttp
  57.         1.2 : UTMP logging build in.
  58.         1.3 : Can be used on normal TOS now.      
  59.         1.4 : - SHELL and HOME dir in passwd file can be both in UNIX
  60.                 and in TOS notation now.
  61.               - Textfile /etc/welcome will be printed if available
  62.                 instead of build in welcome message.
  63.               - Program prints error message now if shell entry
  64.                 in passwd could not be started.
  65.         1.5 : - Getty pid logged in /etc/syslog.
  66.               - Slightly adjusted delay times for modem routines.
  67.               - PURE_C delay function replaced by Delay (modem.c).
  68.         1.6 : - Multiuser behaviour improved by setting the user and
  69.                 group id's before starting a shell.
  70.               - From now on getty can only be run by uid 0 (root).
  71.               - Modem is reset when getty terminates.
  72.               - Extra option (-i) to supply modem init commands from
  73.                 the commandline.
  74.  
  75.    Any questions or suggestions about this program can be send to:
  76.    lemmens@dv.twi.tudelft.nl
  77. */
  78.  
  79. #ifdef __PUREC__
  80. #include <tos.h>
  81. #else
  82. #include <osbind.h>
  83. #endif
  84.  
  85. #include <stdio.h>
  86. #include <string.h>
  87. #include <stdlib.h>
  88. #include <time.h>
  89. #include <fcntl.h>
  90.  
  91. #include "ux_misc.h"
  92. #include "modem.h"
  93.  
  94. /* UNIX headers */
  95.  
  96. #include <utmp.h>
  97. #include <pwd.h>
  98. #include <signal.h>
  99. #include <ioctl.h>    /* ioctl and TIOC */
  100.  
  101. int hwfl,fp,mintflag;
  102. char *errlog;
  103. static struct utmp w;
  104.  
  105. #define MAX_FAIL 4
  106.  
  107. void sleep(unsigned s);
  108.  
  109. void LogMsg(char *txt)
  110. {    FILE *log;
  111.     int x;
  112.     time_t tm;
  113.  
  114.     time(&tm);
  115.     for(x=0;x<10 && (log=fopen(errlog,"a")) == NULL;x++)
  116.         sleep(1);    /* could be opened by another application */
  117.  
  118.     if(log==NULL)        log=stderr;
  119.     fprintf(log,"GETTY (%03d) %.24s: %s\n",Pgetpid(),ctime(&tm),txt);
  120.     if(log != stderr) fclose(log);
  121. }
  122.  
  123. void fatal(char *txt)
  124. {    LogMsg(txt);
  125.     exit(1);
  126. }
  127.  
  128. void Term_Handler()
  129. {    if(! hwfl) mod_reset();
  130.     fatal("Terminate signal received.");
  131. }
  132.  
  133. void log_utmp(struct utmp *w)
  134. {    setutent();
  135.     pututline(w);
  136.     endutent();
  137. }
  138.  
  139. void log_xtmp(struct utmp *w,char *file)
  140. {    utmpname(file);
  141.     setutent();
  142.     lseek(utmp_fd,0,SEEK_END);    /* goto end of file */
  143.     pututline(w);
  144.     endutent();
  145.     utmpname(UTMP_FILE);
  146. }
  147.  
  148. void start_shell(struct passwd *pwent)
  149. {    char shell[100];
  150.     FILE *welcome;
  151.     static char environ[500];
  152.     static char *Badshell   ="Problem starting shell !!\r\n";
  153.     static char *WelcomeTxt ="\r\n\nWelcome on ATARI\r\n";
  154.  
  155.     sprintf(shell,"%c:%.97s",mintflag ? 'u' : 'c',
  156.         ux2dos(pwent->pw_shell));
  157.     
  158.     sprintf(environ,"LOGNAME=%s%cHOME=u:%s%cPATH=%s%cTTYNAME=%s",
  159.         pwent->pw_name,0,ux2dos(pwent->pw_dir),0,PATH,0,w.ut_line);
  160.  
  161.     strncpy(w.ut_user,pwent->pw_name,sizeof(w.ut_user));
  162.  
  163.     Fforce(-1,fp);        /* redirect terminal to line (Pexec) */
  164.  
  165.     if((welcome = fopen(WELCOME,"r")) != NULL)
  166.     {    while(fgets(WelcomeTxt,99,welcome) != NULL)
  167.             Put(WelcomeTxt); 
  168.         fclose(welcome);
  169.     }
  170.     else
  171.         Put(WelcomeTxt);
  172.  
  173. #ifndef DEBUG
  174.  
  175.     if(mintflag)
  176.     {    if((w.ut_pid =(int)Pfork()) == 0)
  177.         {    /* must change uid & gid in a subprocess or it will
  178.                be impossible to change back to uid 0 again !
  179.             */
  180.             (void)Psetuid(pwent->pw_uid);
  181.             (void)Psetgid(pwent->pw_gid);
  182.             w.ut_pid=Pexec(200,shell," ",environ);
  183.             Put(Badshell); /* only reach this if Pexec overlay fails */
  184.             exit(0);
  185.         }
  186.     }
  187.     w.ut_type=USER_PROCESS;
  188.  
  189.     log_utmp(&w);
  190.     log_xtmp(&w,WTMP_FILE);
  191.  
  192.     if(mintflag)
  193.         Pwait3(0,(long *)0); /* wait for shell to exit */
  194.     else if((w.ut_pid=(int)Pexec(0,shell," ",environ)) < 0)
  195.         Put(Badshell);
  196.  
  197. #endif
  198.  
  199.     w.ut_type = DEAD_PROCESS;
  200.     log_xtmp(&w,WTMP_FILE);
  201.  
  202.     Fforce(-1,0);
  203. }
  204.  
  205. void set_baudrate(int baud)
  206. {    struct sgttyb sg;
  207.     struct { char flag; int rate; }
  208.         t[] = {  0,    0,  7,  300,  8,  600,  9,  1200,
  209.                 11, 2400, 12, 4800, 13, 9600, 14, 19200
  210.               };
  211.     int nr,max=(int)(sizeof(t)/sizeof(t[0]));
  212.     
  213.     for(nr=0;baud != t[nr].rate; nr++)
  214.         if(nr>=max)
  215.             fatal("Unsupported baudrate !");
  216.  
  217.     ioctl(0, TIOCGETP, &sg);
  218.     sg.sg_ispeed = sg.sg_ospeed = t[nr].flag;
  219.     ioctl(0, TIOCSETP, &sg);
  220.     /* With the current driver this can only set AUX: port ! */
  221. }
  222.  
  223. int init_modem(int baud,char *cmd)
  224. {    set_baudrate(baud);
  225.     mod_puts(cmd);
  226.     return mod_wait("OK",20,0);
  227. }
  228.  
  229. void daemon_mode(void)
  230. {
  231.     /* if we are the child, kill parent to become a daemon */
  232.     /* proc grp is changed to avoid signal problems (SIGCHLD) */
  233.  
  234.     if(Pfork()) Pwait();    /* wait to be killed !! (gna gna) */
  235.     
  236.     (void)Psetpgrp(0,0);
  237.     (void)Pkill(Pgetppid(),SIGKILL);
  238. }
  239.  
  240. void handle_login(void)
  241. {    int cnt;
  242.     struct passwd *pwent;
  243.     char name[50],pwd[50];
  244.     char *lg_txt="\r\nLogin   : ";
  245.     char *pw_txt="\r\nPassword: ";
  246.     char *er_txt="     Invalid";
  247.  
  248.     for(cnt=0;cnt<MAX_FAIL;cnt++)
  249.     {    do
  250.         {    Put(lg_txt);
  251.             while(Cconis()==0)
  252.                 sleep(1); /* only to avoid heavy system load */
  253.             Get(name,40,1);
  254.         }while(strlen(name)==0);
  255.     
  256.         Put(pw_txt);
  257.         Get(pwd,40,0);
  258.  
  259.         if((pwent=getpwnam(name)) != NULL)
  260.             if(check_pw(pwd,pwent) >= 0)    /* succesfull login */
  261.             {    (void)Pnice(-20);    /* restore normal priority */
  262.                 fflush(stdin);
  263.                 start_shell(pwent);    
  264.                 return;                /* force hangup after logout */
  265.             }
  266.         Put(er_txt);
  267.         strncpy(w.ut_name,name,sizeof(w.ut_name));
  268.         w.ut_type=DEAD_PROCESS;
  269.         log_xtmp(&w,BTMP_FILE);
  270.     }
  271. }
  272.  
  273. void usage(void)
  274. {    fputs(